﻿/// <reference path="../Scripts/jquery-1.7.2.js" />
/// <reference path="../Scripts/knockout-2.1.0.js" />
/// <reference path="../Scripts/knockout.mapping-latest.js" />

/// <reference path="../Scripts/qunit.js" />
/// <reference path="../Scripts/sinon-1.3.4.js" />
/// <reference path="../Scripts/sinon-qunit-1.0.0.js" />

/// <reference path="../aaa/jqueryExtensions.js" />
/// <reference path="../aaa/ActivityFeed.api.js" />
/// <reference path="../aaa/activityFeed.viewModels.ActivityFeed.js" />

$(function () {
    var apiMock;
    var viewModel;

    module("Given update with comments", {
        setup: function () {
            var publishedOn = new Date(1337089291151);
            var date1 = new Date(1337089291151);


            this.initialUpdates =
                [
                    {
                        id: 1, content: "EloMelo", publishedOn: publishedOn.toISOString(), publisher: { id: 'user1', name: 'user1name', photoUrl: 'http://www/photo.com/user1' },
                        comments:
                        [
                            { id: 'comment1', text: 'comment 1111 text', publisher: { id: 'user123', name: 'john comment', photoUrl: 'http://www/photo.com/user123'} }
                        ],
                        likes:
                        [
                            { createdDate: date1, user: { id: 'userL1', name: 'nameL1', photoUrl: 'http://www/photo.com/userL1'} }
                        ]
                    }
                ];

            this.currentUser = { id: 'currentUserId', name: 'currentName', photoUrl: 'http://www/photo.com/currentPhotoUrl' };
        }
    });

    test("When mapUpdatesArray is called, then updates contains observable array of observable objects.", function () {
        var updatesMapper = new activityFeed.UpdatesMapper(this.currentUser, null);
        var updates = ko.observableArray(updatesMapper.mapUpdates(this.initialUpdates));

        ok(updates());

        equal(updates().length, this.initialUpdates.length);

        var firstUpdate = updates()[0];

        ok(firstUpdate.id());
        ok(firstUpdate.content());
        ok(firstUpdate.publisher());
        ok(firstUpdate.publishedOn());
        ok(firstUpdate.comments());
        ok(firstUpdate.likes());

        ok(firstUpdate.publisher());
        ok(firstUpdate.publisher().id);
        ok(firstUpdate.publisher().name);
        ok(firstUpdate.publisher().photoUrl);

        var firstComment = firstUpdate.comments()[0];
        ok(firstComment.publisher(), "like contains publisher");

        var firstLike = firstUpdate.likes()[0];
        ok(firstLike.user(), "like contains user");
    });

    test("When onUpdateViewModelInit method is provided, then each update is extended using this method", function () {
        var onUpdateInitializeMock = sinon.spy("onUpdateInitialize");
        var updatesMapper = new activityFeed.UpdatesMapper(this.currentUser, null, onUpdateInitializeMock);
        var updates = ko.observableArray(updatesMapper.mapUpdates(this.initialUpdates));
        equal(onUpdateInitializeMock.callCount, updates().length);
    });

    test("When mapUpdateToUpdateViewModel is called, then update is converted to UpdateViewModel.", function () {
        var updatesMapper = new activityFeed.UpdatesMapper(this.currentUser, null);
        var update = updatesMapper.mapUpdateToUpdateViewModel(this.initialUpdates[0]);

        ok(update.id());
        ok(update.content());
        ok(update.publisher());
        ok(update.publishedOn());
        ok(update.comments());
        ok(update.likes());

        ok(update.publisher());
        ok(update.publisher().id);
        ok(update.publisher().name);
        ok(update.publisher().photoUrl);

        var firstComment = update.comments()[0];
        ok(firstComment.publisher(), "like contains publisher");

        var firstLike = update.likes()[0];
        ok(firstLike.user(), "like contains user");
    });


    test("When mapCommentToCommentViewModel is called, then comment is converted to CommentViewModel.", function () {
        var updatesMapper = new activityFeed.UpdatesMapper(this.currentUser, null);
        var comment = updatesMapper.mapUpdateToUpdateViewModel(this.initialUpdates[0].comments[0]);

        ok(comment.id(), "like contains id");
        ok(comment.text(), "like contains text");
        ok(comment.publisher(), "like contains publisher");
        ok(comment.publishedOn(), "like contains publishedOn");
    });

    test("When mapLikeToLikeViewModel is called, then like is converted to LikeViewModel.", function () {
        var updatesMapper = new activityFeed.UpdatesMapper(this.currentUser, null);
        var like = updatesMapper.mapLikeToLikeViewModel(this.initialUpdates[0].likes[0]);

        ok(like.user(), "like contains observable user");
    });
});